home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_400
/
406_01
/
atoc
/
preproc.c
< prev
next >
Wrap
Text File
|
1993-11-09
|
6KB
|
205 lines
/*=========================================================================
ATOC proprocessor module
=========================================================================*/
#include <stdio.h>
#include <ctype.h>
#include "atoc.h"
#define STACKSIZE 32
#define INCLUDE_ENVNAME "INCLUDE"
/*-------------------------------------------------------------------------
local global variables
-------------------------------------------------------------------------*/
PRIVATE int ecstack[ STACKSIZE ]; /* stack for endifcount nesting */
PRIVATE int csi = 0; /* current stack index */
/*-------------------------------------------------------------------------
preprocessor( fo, s ) alters new ANSI preprocessor statements into those
commonly supported by older compilers. Also notes a few things we don't
handle yet.
-------------------------------------------------------------------------*/
preprocessor( fo, s )
FILE *fo;
char *s;
{
char *p1, *p2, *p3, *strstr();
/* find first non-white char */
for ( p1 = s; *p1 && isspace( *p1 ); ++p1 )
;
if ( *p1 == '#' )
{
/* remove leading white space */
/* and any white space between # and command */
for ( ++p1; *p1 && isspace( *p1 ); ++p1 )
;
s[ 0 ] = '#';
if ( p1 > &s[ 1 ] )
strcpy( &s[ 1 ], p1 );
/* check for #if, handle nesting of endifcount */
if ( ( p1 = strstr( s, "#if" ) ) != NULL )
{
if ( csi < STACKSIZE )
{
ecstack[ csi++ ] = endifcount;
endifcount = 0;
}
else
{
error( "#if stack overflow" );
return;
}
}
/* check for #elif, convert to #else #if and add extra #endif */
if ( ( p1 = strstr( s, "#elif" ) ) != NULL )
{
fprintf( fo, "#else\n" );
strcpy( p1 + 1, p1 + 3 );
++endifcount;
}
/* check for "#if defined" or "#if ! defined" */
if ( ( p1 = strstr( s, "#if" ) ) != NULL )
{
p2 = strstr( p1, "!" );
if ( ( p3 = strstr( p1, "defined" ) ) != NULL )
{
strcpy( p1, p3 + 7 );
if ( p2 && p2 > p1 && p2 < p3 )
strins( p1, "#ifndef" );
else strins( p1, "#ifdef" );
}
}
/* output any accumulated #endifs */
if ( ( p1 = strstr( s, "#endif" ) ) != NULL )
{
for ( ; endifcount; --endifcount )
fprintf( fo, "#endif\n" );
if ( csi > 0 )
{
endifcount = ecstack[ --csi ];
}
else
{
error( "Too many #endifs" );
return;
}
}
/* handle include files if option selected */
if ( ( p1 = strstr( s, "#include" ) ) != NULL )
{
if ( includeflag )
include( fo, s );
/* else just output the include line */
}
/* check for new # and ## operators that we don't convert */
if ( ( p1 = strstr( s, "#define" ) ) != NULL )
{
if ( strstr( p1 + 7, "##" ) != NULL )
warning( "'##' Token paste operator not converted" );
else if ( strstr( p1 + 7, "#" ) != NULL )
warning( "'#' String literal operator not converted" );
}
}
}
/*-------------------------------------------------------------------------
endif_stack_empty() checks to see if the stack is empty, which it should
be at the time we call.
-------------------------------------------------------------------------*/
int endif_stack_empty()
{
if ( csi == 0 )
return( TRUE );
else return( FALSE );
}
/*-------------------------------------------------------------------------
include( fo, s ) handles an include file line. This is only done if the
-i option was specified on the command line. -il causes us to only handle
local includes (those delimited with " ").
-------------------------------------------------------------------------*/
PRIVATE include( fo, s )
FILE *fo;
char *s;
{
FILE *fi;
char basename[ 80 ], fullname[ 80 ], old_filename[ 80 ];
char *cp, dc, *path, *getenv(), *strchr();
int old_linenumber;
/* find include filename and delimiter type */
if ( ( cp = strchr( s, '\"' ) ) == NULL )
cp = strchr( s, '<' );
if ( cp != NULL )
{
dc = *cp++;
/* if local includes only and this is a <>, forget it... */
if ( localonlyflag && dc == '<' )
return;
}
else
{
error( "Can't find include filename delimiter" );
return;
}
/* copy include filename to basename, delete trailing end of line */
strcpy( basename, cp );
if ( dc == '<' )
dc = '>';
if ( ( cp = strchr( basename, dc ) ) != NULL )
*cp = '\0';
else
{
error( "No trailing delimiter on include filename" );
return;
}
/* open include file, either locally... */
if ( dc == '\"' )
fi = fopen( basename, "r" );
else fi = NULL;
/* or on the INCLUDE path */
if ( fi == NULL )
if ( path = getenv( INCLUDE_ENVNAME ) )
for ( cp = path; path; path = cp )
{
if ( ( cp = strchr( cp, ';' ) ) != NULL )
*cp++ = '\0';
strcpy( fullname, path );
strcat( fullname, "\\" );
strcat( fullname, basename );
if ( ( fi = fopen( fullname, "r" ) ) != NULL )
break;
}
/* set up global variables and recursively call atoc() for include file */
if ( fi != NULL )
{
strcpy( old_filename, filename );
strcpy( filename, basename );
old_linenumber = linenumber;
linenumber = 1;
fprintf( fo, "/* %s */\n", s );
atoc( fi, fo );
fclose( fi );
s[ 0 ] = '\0';
strcpy( filename, old_filename );
linenumber = old_linenumber;
}
else error( "Can't open include file" );
}
/*=======================================================================*/